msg_tool\scripts\softpal\img\pgd/
ge.rs1use super::base::*;
2use crate::ext::io::*;
3use crate::scripts::base::*;
4use crate::types::*;
5use crate::utils::struct_pack::*;
6use anyhow::Result;
7use std::io::{Read, Seek};
8
9#[derive(Debug)]
10pub struct PgdGeBuilder {}
11
12impl PgdGeBuilder {
13 pub fn new() -> Self {
14 Self {}
15 }
16}
17
18impl ScriptBuilder for PgdGeBuilder {
19 fn default_encoding(&self) -> Encoding {
20 Encoding::Cp932
21 }
22
23 fn build_script(
24 &self,
25 buf: Vec<u8>,
26 _filename: &str,
27 _encoding: Encoding,
28 _archive_encoding: Encoding,
29 config: &ExtraConfig,
30 _archive: Option<&Box<dyn Script>>,
31 ) -> Result<Box<dyn Script>> {
32 Ok(Box::new(PgdGe::new(MemReader::new(buf), config)?))
33 }
34
35 fn extensions(&self) -> &'static [&'static str] {
36 &["pgd"]
37 }
38
39 fn script_type(&self) -> &'static ScriptType {
40 &ScriptType::SoftpalPgdGe
41 }
42
43 fn is_image(&self) -> bool {
44 true
45 }
46
47 fn is_this_format(&self, _filename: &str, buf: &[u8], buf_len: usize) -> Option<u8> {
48 if buf_len >= 4 && buf.starts_with(b"GE \0") {
49 return Some(20);
50 }
51 None
52 }
53
54 fn can_create_image_file(&self) -> bool {
55 true
56 }
57
58 fn create_image_file<'a>(
59 &'a self,
60 data: ImageData,
61 _filename: &str,
62 mut writer: Box<dyn WriteSeek + 'a>,
63 options: &ExtraConfig,
64 ) -> Result<()> {
65 let header = PgdGeHeader {
66 offset_x: 0,
67 offset_y: 0,
68 width: data.width,
69 height: data.height,
70 canvas_width: data.width,
71 canvas_height: data.height,
72 mode: 3,
73 _unk: 0,
74 };
75 writer.write_all(b"GE \0")?;
76 header.pack(&mut writer, false, Encoding::Utf8, &None)?;
77 PgdWriter::new(data, options.pgd_fake_compress)
78 .with_method(3)
79 .pack_ge(&mut writer)?;
80 Ok(())
81 }
82}
83
84#[derive(Debug)]
85pub struct PgdGe {
86 header: PgdGeHeader,
87 data: ImageData,
88 fake_compress: bool,
89}
90
91impl PgdGe {
92 pub fn new<T: Read + Seek>(mut input: T, config: &ExtraConfig) -> Result<Self> {
93 let mut magic = [0u8; 4];
94 input.read_exact(&mut magic)?;
95 if &magic != b"GE \0" {
96 return Err(anyhow::anyhow!("Not a valid PGD GE image"));
97 }
98 let header = PgdGeHeader::unpack(&mut input, false, Encoding::Utf8, &None)?;
99 let reader = PgdReader::with_ge_header(input, &header)?;
100 let data = reader.unpack_ge()?;
101 Ok(Self {
102 header,
103 data,
104 fake_compress: config.pgd_fake_compress,
105 })
106 }
107}
108
109impl Script for PgdGe {
110 fn default_output_script_type(&self) -> OutputScriptType {
111 OutputScriptType::Json
112 }
113
114 fn default_format_type(&self) -> FormatOptions {
115 FormatOptions::None
116 }
117
118 fn is_image(&self) -> bool {
119 true
120 }
121
122 fn export_image(&self) -> Result<ImageData> {
123 Ok(self.data.clone())
124 }
125
126 fn import_image<'a>(
127 &'a self,
128 data: ImageData,
129 _filename: &str,
130 mut file: Box<dyn WriteSeek + 'a>,
131 ) -> Result<()> {
132 let mut header = self.header.clone();
133 if data.height != self.data.height {
134 return Err(anyhow::anyhow!(
135 "Image height does not match: expected {}, got {}",
136 self.data.height,
137 data.height
138 ));
139 }
140 if data.width != self.data.width {
141 return Err(anyhow::anyhow!(
142 "Image width does not match: expected {}, got {}",
143 self.data.width,
144 data.width
145 ));
146 }
147 header.mode = 3;
148 file.write_all(b"GE \0")?;
149 header.pack(&mut file, false, Encoding::Utf8, &None)?;
150 PgdWriter::new(data, self.fake_compress)
151 .with_method(3)
152 .pack_ge(&mut file)?;
153 Ok(())
154 }
155}